use std::collections::HashMap;

use dbus::arg;
use dbus::blocking;
use dbus::blocking::stdintf::org_freedesktop_dbus::*;
use dbus::blocking::Proxy;

use crate::Result;

/// Generic D-Bus remote object
pub trait DBusRemoteObject<'a, T, C>
where
    T: blocking::BlockingSender,
    C: std::ops::Deref<Target = T>,
{
    fn proxy(&self) -> &Proxy<'a, C>;

    fn interface(&self) -> &str;

    fn method_call<A, R>(&self, method: &str, args: A) -> Result<R>
    where
        R: arg::ReadAll,
        A: arg::AppendAll,
    {
        self.proxy().method_call(self.interface(), method, args)
    }

    fn get_all(&self) -> Result<HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>> {
        self.proxy().get_all(self.interface())
    }

    fn get<R>(&self, property: &str) -> Result<R>
    where
        R: for<'b> arg::Get<'b>,
    {
        self.proxy().get(self.interface(), property)
    }

    fn set<V>(&self, property: &str, value: V) -> Result<()>
    where
        V: arg::Arg + arg::Append,
    {
        self.proxy().set(self.interface(), property, value)
    }
}
